`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Yu Zihao
// 
// Create Date: 2021/08/02 12:32:43
// Design Name: 
// Module Name: datapath
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision: V1.0
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module datapath(sximm5, sximm8, mdata,
                 writenum, write, readnum, clk, vsel, asel, bsel, shift,
                 ALUop, loada, loadb, loadc, loads, 
                 datapath_out, N_out, V_out, Z_out);
  input [15:0] sximm5, sximm8, mdata;
  input write,clk, asel, bsel;
  input [2:0] writenum, readnum;
  input [1:0] vsel, ALUop, shift;
  input loada,loadb,loadc,loads;
  output [15:0] datapath_out;
  output N_out, V_out, Z_out;
  
  reg [15:0] data_in;
  wire [7:0] PC;
  wire [15:0] Ain, Bin, out;
  wire Z,N,V;
  wire [15:0] data_out;
  reg [15:0] A, B, C;
  reg [2:0] status;
  wire [15:0] in, sout;
  
//  vsel
//    11:mdata
//    10:sximm8
//    01:{8'b0,PC}
//    00:loadc
  always @(*)begin
    case(vsel)
      2'b11 : data_in = mdata;
      2'b10 : data_in = sximm8;
      2'b01 : data_in = {8'b0,PC};
      2'b00 : data_in = C;
      default: data_in = 16'b0;
     endcase
  end
  
  //regfile
  regfile regfile_U0(
    .data_in(data_in),
    .writenum(writenum),
    .write(write),
    .readnum(readnum),
    .clk(clk),
    .data_out(data_out)
  );
  
  assign in = B;
  assign {N_out,V_out,Z_out} = status;
  assign datapath_out = C;
  always @(posedge clk)begin
    A <= loada ? data_out : A;
    B <= loadb ? data_out : B;
    C <= loadc ? out : C;
    status <= loads ? {N,V,Z} : status;
  end
  
  //Shifter
  shifter shifter_U1(
    .in(in),
    .shift(shift),
    .sout(sout)
  );
  
  assign Ain = asel ? 16'b0 : A;
  assign Bin = bsel ? sximm5 : sout;
  
  //ALU
  ALU alu_U2(
    .Ain(Ain),
    .Bin(Bin),
    .ALUop(ALUop),
    .out(out),
    .N(N),
    .V(V),
    .Z(Z)
  );
endmodule
